import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

///
/// @Description: 可拖动的漂浮动作按钮
/// @Author: 下雨了
/// @CreateDate: 2024-01-03 14:29
/// @UpdateUser: 更新者
/// @UpdateDate:  2024-01-03 14:29
/// @UpdateRemark: https://zhuanlan.zhihu.com/p/400581079?utm_id=0
/// @Version: 1.0
///
// final GlobalKey _parentKey = GlobalKey();
// Container(
//   width: 300,
//   height: 300,
//   child: Stack(
//   key: _parentKey,
//   children: [
//     Container(color: Colors.cyan),
//       Center(
//         child: const Text(
//           "FlutterDev's.com",
//           style: const TextStyle(color: Colors.white, fontSize: 24),
//         ),
//       ),
//       DraggableFloatingActionButton(
//         child: Container(
//         width: 60,
//         height: 60,
//         decoration: ShapeDecoration(
//           shape: CircleBorder(),
//           color: Colors.white,
//         ),
//         child: Image.asset("assets/logo.png") ),
//         initialOffset: const Offset(120, 70),
//         parentKey: _parentKey,
//         onPressed: () {},
//       ),
//     ],
//   ),
// )
class DraggableFloatingActionButton extends StatefulWidget {
  final Widget child;

  // 右下角为起点  dx：right dy：bottom
  final Offset initialOffset;
  final VoidCallback onPressed;
  // 需要标住在 Stack上
  final GlobalKey parentKey;

  const DraggableFloatingActionButton({
    super.key,
    required this.child,
    required this.initialOffset,
    required this.onPressed,
    required this.parentKey,
  });

  @override
  State createState() => _DraggableFloatingActionButtonState();
}

class _DraggableFloatingActionButtonState extends State<DraggableFloatingActionButton> {
  final GlobalKey _key = GlobalKey();

  bool isDragging = false;
  late Offset offset;
  late Offset minOffset;
  late Offset maxOffset;

  void updatePosition(PointerMoveEvent pointerMoveEvent) {
    double newOffsetX = offset.dx - pointerMoveEvent.delta.dx;
    double newOffsetY = offset.dy - pointerMoveEvent.delta.dy;

    if (newOffsetX < minOffset.dx) {
      newOffsetX = minOffset.dx;
    } else if (newOffsetX > maxOffset.dx) {
      newOffsetX = maxOffset.dx;
    }

    if (newOffsetY < minOffset.dy) {
      newOffsetY = minOffset.dy;
    } else if (newOffsetY > maxOffset.dy) {
      newOffsetY = maxOffset.dy;
    }

    setState(() {
      offset = Offset(newOffsetX, newOffsetY);
    });
  }

  void setBoundary(Duration timeStamp) {
    // 父组件
    final RenderBox parentRenderBox = widget.parentKey.currentContext?.findRenderObject() as RenderBox;
    // 当前组件
    final RenderBox renderBox = _key.currentContext?.findRenderObject() as RenderBox;
    try {
      final Size parentSize = parentRenderBox.size;
      final Size size = renderBox.size;

      setState(() {
        minOffset = const Offset(0, 0);
        maxOffset = Offset(parentSize.width - size.width, parentSize.height - size.height);
      });
    } catch (e) {
      if (kDebugMode) {
        print('catch: $e');
      }
    }
  }

  @override
  void initState() {
    super.initState();
    offset = widget.initialOffset;

    WidgetsBinding.instance.addPostFrameCallback(setBoundary);
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      right: offset.dx,
      bottom: offset.dy,
      child: Listener(
        onPointerMove: (PointerMoveEvent pointerMoveEvent) {
          updatePosition(pointerMoveEvent);
          setState(() {
            isDragging = true;
          });
        },
        onPointerUp: (PointerUpEvent pointerUpEvent) {
          if (isDragging) {
            setState(() {
              isDragging = false;
            });
          } else {
            widget.onPressed();
          }
        },
        child: Container(
          key: _key,
          child: widget.child,
        ),
      ),
    );
  }
}
